package com.jfinal.code.eclipse.plugin.wizards.ui;

import java.io.File;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.jfinal.code.eclipse.plugin.generator.db.DbType;
import com.jfinal.code.eclipse.plugin.i18n.I18n;
import com.jfinal.code.eclipse.plugin.wizards.page.DatabaseInfoWizardPage;
import com.jfinal.code.eclipse.plugin.wizards.prop.Key;
import com.jfinal.code.eclipse.plugin.wizards.prop.PropertiesUtils;

/**
 * <p>
 * 一种相思花自飘零水自流，两处闲愁独自寂寞上心头。<br>
 * 梦回青青池畔回忆灯火阑珊，一杯苦酒恰似落花情几时休。
 * </p>
 * 理论上这里的控件都会被创建，不对其进行非空判断。
 * @author yaolin
 * @see com.jfinal.code.eclipse.plugin.generator.db.DbType
 */
public class DatabaseInfoUI {

	/**
	 * 数据库类型
	 */
	private final String[] databaseTypeList = DbType.getNames(); //{ "MySQL", "Oracle" };
	/**
	 * 默认选中的数据库类型
	 */
	private final int defaultDatabaseTypeSelectIndex = DbType.MySQL.ordinal();
	private final String[] defaultJdbcUrlTemplateList = DbType.getJdbcUrlTmpls();
	/*{
		 "jdbc:mysql://%s:%s/%s" 
		,"jdbc:oracle:thin:@%s:%s:%s" 
	};*/
	private final String[] defaultJdbcDriverClassNameList = DbType.getJdbcDriverClassNames();
	/*{
		 "com.mysql.jdbc.Driver"
		,"oracle.jdbc.driver.OracleDriver"
	};*/
	private final DatabaseInfoWizardPage page;
	private final Shell shell;
	private final Composite parent;

	public DatabaseInfoUI(DatabaseInfoWizardPage page, Shell shell, Composite parent) {
		this.page = page;
		this.shell = shell;
		this.parent = parent;
	}

	/**
	 * 创建是否加载配置文件的按钮
	 */
	public Button createLoadPropertyButton() {
		final Button button = new Button(parent, SWT.CHECK);
		button.setText(I18n.databaseInfoUI_loadPropertyLabel);
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				page.getPropertyText().setEnabled(button.getSelection());
			}
		});
		return button;
	}
	/**
	 * 配置文件Text
	 */
	public Text createPropertyText() {
		Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.setEnabled(false); // 默认不可用
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				if (!page.getLoadPropertyButton().getSelection()) {
					if (page.getPropertyText().getText().trim().length() > 0) { // no loop
						page.getPropertyText().setText(""); 
					}
				} else {
					try {
						// 加载配置文件
						PropertiesUtils.load(page.getPropertyText().getText().trim());
						page.getServerNameText().setText(PropertiesUtils.get(Key.dbInfo_server, ""));
						page.getPortText().setText(PropertiesUtils.get(Key.dbInfo_port, ""));
						page.getDatabaseNameText().setText(PropertiesUtils.get(Key.dbInfo_database, ""));
						page.getUsernameText().setText(PropertiesUtils.get(Key.dbInfo_username, ""));
						page.getPasswordText().setText(PropertiesUtils.get(Key.dbInfo_password, ""));
						page.getDriverLocationText().setText(PropertiesUtils.get(Key.dbInfo_driverJar, "")
							.replace("\\", File.separator).replace("/", File.separator));
						page.getJdbcUrlText().setText(PropertiesUtils.get(Key.dbInfo_url, ""));
						page.getJdbcDriverClassNameText().setText(PropertiesUtils.get(Key.dbInfo_driverClassName, ""));
					} catch (IOException ex) {
						MessageBox box = new MessageBox(shell, SWT.ICON_ERROR);
						box.setMessage(ex.getMessage());
						box.open();
					}
				}
			}
		});
		Button button = new Button(parent, SWT.PUSH);
		button.setText("Browse...");
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shell, SWT.OPEN);
				dialog.setText(I18n.databaseInfoUIEvent_pleaseSelectDriverFile);
				String fileName = dialog.open();
				page.getPropertyText().setText(fileName == null ? "" : fileName);
			}
		});
		return text;
	}
	/**
	 * 创建数据库类型下拉选择框
	 */
	public Combo createDatabaseTypeCombo() {
		Label textLabel = new Label(parent, SWT.NULL);
		textLabel.setText(I18n.databaseInfoUI_databaseTypeLabel);
		final Combo combo = new Combo(parent, SWT.READ_ONLY);
		combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		combo.setItems(databaseTypeList);
		combo.select(defaultDatabaseTypeSelectIndex); // 默认选中第一项
		combo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int i = combo.getSelectionIndex();
				setDefaultValueByComboIndex(i);
				page.getServerNameText().setEnabled(i != DbType.SQLLite3.ordinal());
				page.getPortText().setEnabled(i != DbType.SQLLite3.ordinal());
				// 设置默认的端口号
				if (i == DbType.MySQL.ordinal()) {
					page.getPortText().setText("3306");
				} else if (i == DbType.Oracle.ordinal()) {
					page.getPortText().setText("1521");
				} else if (i == DbType.SQLServer.ordinal()) {
					page.getPortText().setText("1433");
				} else if (i == DbType.PostgreSQL.ordinal()) {
					page.getPortText().setText("5432");
				}
			}
		});
		new Label(parent, SWT.NULL); // 只是占位
		return combo;
	}

	/**
	 * 创建主机名（IP）输入框
	 */
	public Text createServerNameText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_serverNameLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				Validator.validatorEmptyString(page);
				setDefaultValueByComboIndex(page.getDatabaseTypeCombo().getSelectionIndex());
			}
		});
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建端口号输入框
	 */
	public Text createPortText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_portLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				Validator.validatorEmptyString(page);
				setDefaultValueByComboIndex(page.getDatabaseTypeCombo().getSelectionIndex());
			}
		});
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建数据库名称输入框
	 */
	public Text createDatabaseNameText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_databaseNameLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				Validator.validatorEmptyString(page);
				setDefaultValueByComboIndex(page.getDatabaseTypeCombo().getSelectionIndex());
			}
		});
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建用户名输入框
	 */
	public Text createUsernameText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_usernameLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ValidatorModifyAdapter());
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建密码输入框
	 */
	public Text createPasswordText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_passwordLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
		text.setEchoChar('*');
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				// do nothing
			}
		});
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建数据库驱动包位置输入框
	 */
	public Text createDriverLocationText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_driverLocationLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ValidatorModifyAdapter());
		//text.setEnabled(false); // 默认使用默认的驱动，不能编辑
		Button button = new Button(parent, SWT.PUSH);
		button.setText("Browse...");
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shell, SWT.OPEN);
				dialog.setText(I18n.databaseInfoUIEvent_pleaseSelectDriverFile);
				String fileName = dialog.open();
				text.setText(fileName == null || !fileName.endsWith(".jar") ? "" : fileName);
			}
		});
		return text;
	}

	/**
	 * 创建JDBC URL输入框
	 */
	public Text createJdbcUrlText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_jdbcUrlLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ValidatorModifyAdapter());
		text.setText(String.format(defaultJdbcUrlTemplateList[defaultDatabaseTypeSelectIndex], "", "", ""));
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}

	/**
	 * 创建JDBC Driver Class Name输入框
	 */
	public Text createJdbcDriverClassNameText() {
		Label label = new Label(parent, SWT.NULL);
		label.setText(I18n.databaseInfoUI_jdbcDriverClassNameLabel);
		final Text text = new Text(parent, SWT.BORDER | SWT.SINGLE);
		text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		text.addModifyListener(new ValidatorModifyAdapter());
		text.setText(defaultJdbcDriverClassNameList[defaultDatabaseTypeSelectIndex]);
		new Label(parent, SWT.NULL); // 只是占位
		return text;
	}
	
	// ------------private------------
	/**
	 * 根据Combo的数据库类型设置默认值
	 * @param index
	 */
	private void setDefaultValueByComboIndex(int index) {
		String url = "";
		if (index != DbType.SQLLite3.ordinal()) {
			url = String.format(defaultJdbcUrlTemplateList[index],
				page.getServerNameText().getText().trim(), 
				page.getPortText().getText().trim(),
				page.getDatabaseNameText().getText().trim());
		} else {
			url = String.format(defaultJdbcUrlTemplateList[index],page.getDatabaseNameText().getText().trim());
		}
		page.getJdbcUrlText().setText(url);
		page.getJdbcDriverClassNameText().setText(defaultJdbcDriverClassNameList[index]);
	}
	
	/**
	 * 文本校验适配
	 * @author yaolin
	 */
	class ValidatorModifyAdapter implements ModifyListener {
		@Override
		public void modifyText(ModifyEvent e) {
			Validator.validatorEmptyString(page);
		}
	}
	
	/**
	 * 校验
	 * @author yaolin
	 */
	public static class Validator {
		/**
		 * 非空字符串校验
		 */
		public static void validatorEmptyString(DatabaseInfoWizardPage page) {
			if (page.getServerNameText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_serverNameLabel));
				return; // 有错误就不需要往下验证了。
			}
			if (page.getPortText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_portLabel));
				return;
			}
			if (page.getDatabaseNameText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_databaseNameLabel));
				return;
			}
			if (page.getUsernameText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_usernameLabel));
				return;
			}
			if (page.getDriverLocationText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_driverLocationLabel));
				return;
			}
			if (page.getJdbcUrlText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_jdbcUrlLabel));
				return;
			}
			if (page.getJdbcDriverClassNameText().getText().trim().length() == 0) {
				updateStatus(page, String.format(I18n.error_empty_string, I18n.databaseInfoUI_jdbcDriverClassNameLabel));
				return;
			}
			updateStatus(page, null);
		}
		/**
		 * 设置错误提示信息
		 * @param message msg
		 */
		private static void updateStatus(DatabaseInfoWizardPage page, String message) {
			page.setErrorMessage(message);
			page.setPageComplete(message == null);
		}
	}
}
